package com.fzy.core.system.action;

import freemarker.ext.beans.BeansWrapper;
import freemarker.template.Configuration;
import ge.core.system.entity.Entity;
import ge.core.system.entity.Mapping;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.FileUtils;

import com.fzy.core.system.entity.EntityWrapper;
import com.fzy.core.system.entity.MappingWrapper;
import com.fzy.core.system.service.DbService;
import com.fzy.core.utils.BuilderUtils;
import com.fzy.core.utils.IOUtils;
import com.fzy.core.utils.U;
import com.fzy.core.webwork.BaseAction;
import com.fzy.core.webwork.MyValidationAware;
import com.opensymphony.xwork.Preparable;

public class GenerateAction extends BaseAction{
	Long id;
	List moduleIds;
	List entityIds;
	List tableNames;
	List generatedTypes;
	String errorDispatch;
	DbService dbService;
	String appPath;
	
	// to delete entities
	List ids;

	public String execute() throws Exception {
		Mapping mapping = (Mapping)dbService.get(Mapping.class, id);
		List entities = dbService.getEntitiesByMappingId(id);
		MappingWrapper mappingWrapper = new MappingWrapper();
		mappingWrapper.setData(mapping);
		List entityWrappers = new ArrayList();
		for (Iterator iterator = entities.iterator(); iterator.hasNext();) {
			Entity entity = (Entity) iterator.next();
			EntityWrapper entityWrapper = dbService.getEntityWrapperByEntityId(entity.getId());
			entityWrapper.setMapping(mappingWrapper);
			
			entityWrappers.add(entityWrapper);
		}
		mappingWrapper.setEntities(entityWrappers);
		
		String outputPath = "/output";
		
		FileUtils.deleteDirectory(new File(appPath + outputPath));
		
		String templatePath = "/ge-templates";
		Configuration freemarkerEngine = BuilderUtils.getFreemarkerEngine(templatePath);
		
		String dirPath = "/doc";
		String fileName = "schema-oracle.sql";
		String templateName = "schema-oracle.ftl";
		writeMapping(mappingWrapper, freemarkerEngine, templateName, fileName, appPath + outputPath + dirPath);
		
		fileName = "schema-h2.sql";
		templateName = "schema-h2.ftl";
		writeMapping(mappingWrapper, freemarkerEngine, templateName, fileName, appPath + outputPath + dirPath);
		
		fileName = "comments-oracle.sql";
		templateName = "comments-oracle.ftl";
		writeMapping(mappingWrapper, freemarkerEngine, templateName, fileName, appPath + outputPath + dirPath);
		
		dirPath = "/src";
		fileName = ".java";
		templateName = "entity.ftl";
		String prefixPackage = "entity";
		writeEntity(entityWrappers, freemarkerEngine, templateName, fileName, prefixPackage, appPath
				+ outputPath + dirPath);
		
		fileName = ".hbm.xml";
		templateName = "entity-hbm.ftl";
		prefixPackage = "entity";
		writeEntity(entityWrappers, freemarkerEngine, templateName, fileName, prefixPackage, appPath
				+ outputPath + dirPath);
		
		fileName = "_zh_CN.properties";
		templateName = "entity-properties-zh_CN.ftl";
		prefixPackage = "entity";
		writeEntity(entityWrappers, freemarkerEngine, templateName, fileName, prefixPackage, appPath
				+ outputPath + dirPath);
		
		fileName = "-validation.xml";
		templateName = "entity-validation.ftl";
		prefixPackage = "entity";
		writeEntity(entityWrappers, freemarkerEngine, templateName, fileName, prefixPackage, appPath
				+ outputPath + dirPath);
		
		fileName = "ListVo.java";
		templateName = "service-list-vo.ftl";
		prefixPackage = "service";
		writeEntity(entityWrappers, freemarkerEngine, templateName, fileName, prefixPackage, appPath
				+ outputPath + dirPath);
		
		fileName = "ListMapper.java";
		templateName = "service-list-mapper.ftl";
		prefixPackage = "service";
		writeEntity(entityWrappers, freemarkerEngine, templateName, fileName, prefixPackage, appPath
				+ outputPath + dirPath);
		
		addActionMessage(getText("success.save"));
		return "redirect:input.do?id="+ id;
	}
	
	public String deleteEntities() throws Exception {
		dbService.deleteEntities(ids);
		
		addActionMessage(getText("success.save"));
		return "redirect:input.do?id="+ id;
	}

	
	private void writeMapping(MappingWrapper mappingWrapper, Configuration freemarkerEngine, String templateName, String fileName, String path){
		Map data = new HashMap();
		data.put("mapping", mappingWrapper);
		data.put("statics", BeansWrapper.getDefaultInstance().getStaticModels());
		String out = BuilderUtils.produce(freemarkerEngine, templateName, data);
		IOUtils.write(out, fileName, path );
	}
	
	private void writeEntity(List entityWrappers, Configuration freemarkerEngine, String templateName, String fileName, String prefixPackage, String path) {
		for (Iterator iterator = entityWrappers.iterator(); iterator.hasNext();) {
			EntityWrapper e = (EntityWrapper) iterator.next();
			Map data = new HashMap();
			data.put("entity", e);
			data.put("statics", BeansWrapper.getDefaultInstance()
					.getStaticModels());
			data.put("prefixPackage", prefixPackage);
			String out = BuilderUtils.produce(freemarkerEngine, templateName, data);
			IOUtils.write(out, e.getNameCapital() + fileName, path + "/" + e.getPath() + "/"
					+ prefixPackage);
		}
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public List getModuleIds() {
		return moduleIds;
	}

	public void setModuleIds(List moduleIds) {
		this.moduleIds = moduleIds;
	}

	public List getEntityIds() {
		return entityIds;
	}

	public void setEntityIds(List entityIds) {
		this.entityIds = entityIds;
	}

	public List getTableNames() {
		return tableNames;
	}

	public void setTableNames(List tableNames) {
		this.tableNames = tableNames;
	}

	public List getGeneratedTypes() {
		return generatedTypes;
	}

	public void setGeneratedTypes(List generatedTypes) {
		this.generatedTypes = generatedTypes;
	}

	public void setDbService(DbService dbService) {
		this.dbService = dbService;
	}

	public void setAppPath(String appPath) {
		this.appPath = appPath;
	}

	public List getIds() {
		return ids;
	}

	public void setIds(List ids) {
		this.ids = ids;
	}

}
